<template>
  <div
    ref="selectRef"
    :class="['toolbar-select-wrapper', selectClass]"
    :style="{ width: selectWidth }"
  >
    <!-- 触发器 -->
    <div
      ref="selectTriggerRef"
      :class="[
        'toolbar-select-trigger',
        {
          disabled: disabled,
          'is-open': state.expanded,
          'is-focused': isFocused,
        },
      ]"
      @click="toggleMenu"
      @mouseenter="state.inputHovering = true"
      @mouseleave="state.inputHovering = false"
      tabindex="0"
      @focus="handleFocus"
      @blur="handleBlur"
    >
      <!-- 前缀插槽 -->
      <div v-if="$slots.prefix" class="toolbar-select-prefix">
        <slot name="prefix" />
      </div>

      <!-- 选中内容区域 -->
      <div ref="selectionRef" class="toolbar-select-selection">
        <!-- 多选：标签列表 -->
        <template v-if="multiple">
          <div
            v-for="item in state.selected"
            :key="getValueKey(item)"
            class="toolbar-select-tag"
          >
            <slot name="tag" :label="item.currentLabel" :value="item.value">
              <span class="toolbar-select-tag-text">{{
                item.currentLabel
              }}</span>
              <span
                v-if="!disabled && !item.isDisabled"
                class="toolbar-select-tag-close"
                @click.stop="deleteTag(item)"
              >
                ×
              </span>
            </slot>
          </div>
        </template>

        <!-- 单选：显示选中值或占位符 -->
        <template v-else>
          <span v-if="shouldShowPlaceholder" class="toolbar-select-placeholder">
            {{ currentPlaceholder }}
          </span>
          <span v-else class="toolbar-select-value">
            <slot name="label" :label="state.selectedLabel" :value="modelValue">
              {{ state.selectedLabel }}
            </slot>
          </span>
        </template>
      </div>

      <!-- 后缀图标 -->
      <div class="toolbar-select-suffix">
        <span
          v-if="showClose && clearIcon"
          class="toolbar-select-clear"
          @click.stop="handleClear"
        >
          {{ clearIcon }}
        </span>
        <span
          v-else
          class="toolbar-select-arrow i-ri-arrow-down-s-line"
          :class="{ 'is-open': state.expanded }"
        ></span>
      </div>
    </div>

    <!-- 下拉菜单 -->
    <teleport to="body">
      <SelectDropdown
        v-if="state.expanded"
        ref="selectDropdownComponentRef"
        :filterable="filterable"
        :placeholder="placeholder"
        :select-width="selectWidth"
        :select-floating-styles="selectFloatingStyles"
      >
        <template #empty>
          <slot name="empty">
            <div class="toolbar-select-empty">暂无数据</div>
          </slot>
        </template>
        <Option
          v-for="option in propsOptions"
          :key="getOptionKey(option)"
          :value="option.value"
          :label="option.label"
          :disabled="option.disabled"
        >
          <slot name="option" :option="option">
            <span>{{ option.label }}</span>
          </slot>
        </Option>
      </SelectDropdown>
    </teleport>
  </div>
</template>

<script setup lang="ts">
import {
  computed,
  onBeforeUnmount,
  onMounted,
  provide,
  reactive,
  ref,
  watch,
  nextTick,
} from "vue";
import { useFloating, offset, flip, shift, autoUpdate } from "@floating-ui/vue";
import { useSelect } from "./useSelect";
import { selectKey } from "./token";
import type { SelectContext, SelectProps, SelectOptionProxy } from "./types";
import SelectDropdown from "./SelectDropdown.vue";
import Option from "./Option.vue";
import {
  closeAllToolbarPopups,
  onCloseAllToolbarPopups,
  type CloseAllToolbarPopupsEventDetail,
} from "../utils/toolbarPopupManager";

defineOptions({
  name: "ToolbarSelect",
  inheritAttrs: false,
});

const props = withDefaults(defineProps<SelectProps>(), {
  placeholder: "请选择",
  options: () => [],
  clearable: false,
  filterable: false,
  multiple: false,
  selectWidth: "120px",
  disabled: false,
  size: "sm",
});

const emit = defineEmits<{
  (e: "update:modelValue", value: any): void;
  (e: "change", value: any): void;
  (e: "clear"): void;
  (e: "focus", event: FocusEvent): void;
  (e: "blur", event: FocusEvent): void;
}>();

// 使用核心逻辑
const propsRef = ref(props);
const {
  state,
  selectRef,
  selectTriggerRef,
  selectDropdownRef: selectDropdownRefFromUse,
  optionsArray,
  setSelected,
  onOptionCreate,
  onOptionDestroy,
  handleOptionSelect,
} = useSelect(propsRef, emit as any);

// SelectDropdown 组件实例的 ref
const selectDropdownComponentRef = ref<InstanceType<
  typeof SelectDropdown
> | null>(null);

// 获取 SelectDropdown 的 DOM 元素
const selectDropdownRef = computed<HTMLElement | null>(() => {
  if (selectDropdownComponentRef.value) {
    // 从组件实例获取暴露的 DOM 元素
    const exposed = selectDropdownComponentRef.value as any;
    const domRef = exposed.selectDropdownRef;
    // 确保返回的是 DOM 元素
    if (domRef && typeof domRef.contains === "function") {
      return domRef;
    }
  }
  // 如果没有从组件获取到，尝试从 useSelect 中获取
  return selectDropdownRefFromUse.value;
});

// 监听 props 变化，更新 propsRef
watch(
  () => props,
  () => {
    propsRef.value = props;
  },
  { deep: true }
);

// 使用 floating-ui 定位下拉菜单
const { floatingStyles: selectFloatingStyles } = useFloating(
  selectTriggerRef,
  selectDropdownRef,
  {
    placement: "bottom-start",
    middleware: [offset(4), flip(), shift({ padding: 5 })],
    whileElementsMounted: autoUpdate,
    open: computed(() => state.expanded),
  }
);

// 从 props.options 创建的选项
const propsOptions = computed(() => props.options || []);

// 计算属性
const selectClass = computed(() => `select-${props.size}`);

const isFocused = ref(false);

const shouldShowPlaceholder = computed(() => {
  if (props.multiple) {
    return state.selected.length === 0;
  }
  return !state.selectedLabel || state.selectedLabel === "";
});

const currentPlaceholder = computed(() => {
  return props.placeholder || "请选择";
});

const showClose = computed(() => {
  return (
    props.clearable &&
    !props.disabled &&
    state.inputHovering &&
    (props.multiple ? state.selected.length > 0 : state.selectedLabel !== "")
  );
});

const clearIcon = computed(() => {
  return showClose.value ? "×" : null;
});

// 方法
const getValueKey = (item: SelectOptionProxy) => {
  return item.value;
};

const getOptionKey = (option: { value: any; label: string }) => {
  return option.value;
};

const toggleMenu = () => {
  if (props.disabled) return;
  if (!state.expanded) {
    // 打开时，先关闭所有其他弹窗
    closeAllToolbarPopups(selectRef.value, "select");
  }
  state.expanded = !state.expanded;
};

const handleFocus = (event: FocusEvent) => {
  isFocused.value = true;
  emit("focus", event);
};

const handleBlur = (event: FocusEvent) => {
  isFocused.value = false;
  emit("blur", event);
  // 如果焦点不在下拉菜单内，关闭下拉菜单
  const relatedTarget = event.relatedTarget as Node | null;
  const dropdownElement = selectDropdownRef.value;
  if (
    relatedTarget &&
    !dropdownElement?.contains(relatedTarget) &&
    !selectRef.value?.contains(relatedTarget)
  ) {
    state.expanded = false;
  }
};

const handleClickOutside = (event: MouseEvent) => {
  const target = event.target as Node;
  const dropdownElement = selectDropdownRef.value;
  if (selectRef.value?.contains(target) || dropdownElement?.contains(target)) {
    return;
  }
  state.expanded = false;
};

// 点击外部关闭监听器
let clickOutsideHandler: ((event: MouseEvent) => void) | null = null;

watch(
  () => state.expanded,
  (expanded) => {
    if (expanded) {
      nextTick(() => {
        // 延迟添加监听，避免立即触发
        setTimeout(() => {
          clickOutsideHandler = (event: MouseEvent) => {
            handleClickOutside(event);
          };
          document.addEventListener("click", clickOutsideHandler, false);
        }, 100);
      });
    } else {
      if (clickOutsideHandler) {
        document.removeEventListener("click", clickOutsideHandler, false);
        clickOutsideHandler = null;
      }
    }
  }
);

const deleteTag = (item: SelectOptionProxy) => {
  if (props.multiple) {
    const currentValue = Array.isArray(props.modelValue)
      ? [...props.modelValue]
      : [];
    const index = currentValue.indexOf(item.value);
    if (index > -1) {
      currentValue.splice(index, 1);
      emit("update:modelValue", currentValue);
      emit("change", currentValue);
    }
  }
};

const handleClear = (event: Event) => {
  event.stopPropagation();
  const value = props.multiple ? [] : undefined;
  emit("update:modelValue", value);
  emit("change", value);
  emit("clear");
};

// 提供 context 给子组件（响应式）
const context: SelectContext = reactive({
  props: propsRef,
  state,
  selectRef: selectRef.value,
  selectTriggerRef: selectTriggerRef.value,
  selectDropdownRef: selectDropdownRefFromUse.value,
  optionsArray,
  setSelected,
  onOptionCreate,
  onOptionDestroy,
  handleOptionSelect,
});

provide(selectKey, context);

// 监听 ref 变化，更新 context
watch(selectRef, (newRef) => {
  if (newRef) {
    context.selectRef = newRef;
  }
});
watch(selectTriggerRef, (newRef) => {
  if (newRef) {
    context.selectTriggerRef = newRef;
  }
});
watch(selectDropdownRefFromUse, (newRef) => {
  if (newRef) {
    context.selectDropdownRef = newRef;
  }
});

// 监听 selectDropdownComponentRef 变化，更新 useSelect 中的 ref
watch(selectDropdownComponentRef, (componentInstance) => {
  if (componentInstance) {
    const exposed = componentInstance as any;
    if (exposed.selectDropdownRef) {
      selectDropdownRefFromUse.value = exposed.selectDropdownRef;
    }
  }
});

// 监听 modelValue 变化，更新选中状态
watch(
  () => props.modelValue,
  () => {
    setSelected();
  },
  { deep: true, immediate: true }
);

// 监听 options 变化
watch(
  () => props.options,
  () => {
    setSelected();
  },
  { deep: true }
);

// 监听关闭所有弹窗的事件
const handleCloseAllPopups = (
  event: CustomEvent<CloseAllToolbarPopupsEventDetail>
) => {
  const { currentInstance, excludeTypes } = event.detail;
  // 如果当前实例不是当前 Select，或者被排除，则关闭
  if (
    currentInstance !== selectRef.value &&
    !excludeTypes?.includes("select") &&
    state.expanded
  ) {
    state.expanded = false;
  }
};

let cleanupPopupListener: (() => void) | null = null;

onMounted(() => {
  setSelected();
  // 添加监听，保存清理函数
  cleanupPopupListener = onCloseAllToolbarPopups(handleCloseAllPopups);
});

onBeforeUnmount(() => {
  // 清理点击外部监听器
  if (clickOutsideHandler) {
    document.removeEventListener("click", clickOutsideHandler, false);
    clickOutsideHandler = null;
  }
  // 清理弹窗事件监听
  if (cleanupPopupListener) {
    cleanupPopupListener();
    cleanupPopupListener = null;
  }
});

// 暴露方法给父组件
defineExpose({
  focus: () => {
    selectTriggerRef.value?.focus();
  },
  blur: () => {
    selectTriggerRef.value?.blur();
  },
});
</script>

<style scoped lang="scss">
.toolbar-select-wrapper {
  position: relative;
  display: inline-block;
  margin: 0 2px;
}

.toolbar-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px;
  height: 24px;
  border: 1px solid var(--editor-border-color);
  border-radius: var(--editor-radius-medium);
  background: var(--editor-color-white);
  cursor: pointer;
  font-size: var(--editor-font-size);
  color: var(--editor-text-color);
  transition: all 0.2s;
  position: relative;
  gap: 4px;
}

.toolbar-select-trigger:hover:not(.disabled) {
  border-color: var(--editor-border-color-dark);
}

.toolbar-select-trigger.is-open {
  border-color: var(--editor-primary-color);
  box-shadow: 0 0 0 2px rgba(52, 128, 249, 0.2);
}

.toolbar-select-trigger.is-focused {
  border-color: var(--editor-primary-color);
}

.toolbar-select-trigger.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background-color: var(--editor-container-background);
  color: var(--editor-text-color-disabled);
}

.toolbar-select-prefix {
  display: flex;
  align-items: center;
}

.toolbar-select-selection {
  flex: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  min-width: 0;
  overflow: hidden;
}

.toolbar-select-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  background: var(--editor-primary-color);
  color: var(--editor-color-white);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1;
}

.toolbar-select-tag-text {
  white-space: nowrap;
}

.toolbar-select-tag-close {
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.2s;
}

.toolbar-select-tag-close:hover {
  opacity: 1;
}

.toolbar-select-placeholder {
  color: var(--editor-text-color-light);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toolbar-select-value {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--editor-text-color);
}

.toolbar-select-suffix {
  display: flex;
  align-items: center;
  gap: 4px;
}

.toolbar-select-clear {
  cursor: pointer;
  color: var(--editor-text-color-light);
  font-size: 16px;
  line-height: 1;
  transition: color 0.2s;
  padding: 2px;
}

.toolbar-select-clear:hover {
  color: var(--editor-text-color);
}

.toolbar-select-arrow {
  margin-left: 4px;
  font-size: var(--editor-font-size-small);
  color: var(--editor-text-color-light);
  transition: transform 0.2s;
  display: inline-block;
  line-height: 1;
}

.toolbar-select-arrow.is-open {
  transform: rotate(180deg);
}

.toolbar-select-empty {
  text-align: center;
  color: var(--editor-text-color-light);
  padding: 20px;
}
</style>
